package org.example.analysis.service;

import lombok.extern.slf4j.Slf4j;
import org.example.analysis.model.ClassComplexity;
import org.example.analysis.model.MethodComplexity;
import org.example.analysis.model.config.AnalysisConfig;
import org.example.analysis.model.entity.EntryPointInfo;
import org.example.analysis.model.entity.JavaClassInfo;
import org.example.analysis.model.entity.JavaMethodInfo;
import org.example.analysis.model.entity.ProjectInfo;
import org.example.analysis.service.analyzer.ClassComplexityAnalyzer;
import org.example.analysis.service.analyzer.EntryPointAnalyzer;
import org.example.analysis.service.analyzer.ProjectAnalyzer;
import org.example.analysis.service.dataobj.ClassDataObject;
import org.example.analysis.service.dataobj.MethodDataObject;
import org.example.analysis.service.dataobj.ProjectDataObject;

import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 代码分析应用主方法
 */
@Slf4j
public class CodeAnalysisManager {
    private final CodeAnalysisDbService codeAnalysisService;
    private final ReportGenerateService reportGenerateService;
    private final ProjectAnalyzer projectAnalyzer;
    private final CodeAnalysisDbService codeAnalysisDbService;
    private final EntryPointAnalyzer entryPointAnalyzer;
    private final MethodComplexityAnalyzer methodComplexityAnalyzer;
    private AnalysisConfig  analysisConfig;

    public CodeAnalysisManager(AnalysisConfig analysisConfig) {
        this.analysisConfig = analysisConfig;
        this.codeAnalysisService = new CodeAnalysisDbService();
        this.reportGenerateService = new ReportGenerateService();
        this.projectAnalyzer = new ProjectAnalyzer();
        this.codeAnalysisDbService = new CodeAnalysisDbService();
        this.entryPointAnalyzer = new EntryPointAnalyzer();
        this.methodComplexityAnalyzer = new MethodComplexityAnalyzer();
    }

    public void analyzeProject(String projectName) {
        ProjectInfo projectInfo = codeAnalysisDbService.getProjectInfo(projectName);
        String filePath = projectInfo.getProjectPath();
        ProjectDataObject projectDataObject = projectAnalyzer.analyzeCode(new File(filePath));
        projectDataObject.setProjectName(projectName);
        if (analysisConfig.isMethodComplexity()) {
            analyzeMethodComplexity(projectDataObject);
        }
        if (analysisConfig.isClassComplexity()) {
            analyzeClassComplexity(projectDataObject);
        }
        if(analysisConfig.isSaveMethodInfo()){
            saveMethodInfo(projectDataObject);
        }
        if (analysisConfig.isSaveEntryPoint()) {
            saveEntryPointInfo(projectDataObject);
        }
        if(analysisConfig.isSaveClassInfo()){
            saveClassInfo(projectDataObject);
        }
    }

    public void analyzeClassComplexity(ProjectDataObject projectDataObject) {
        ClassComplexityAnalyzer classComplexityAnalyzer = new ClassComplexityAnalyzer();
        List<ClassDataObject> classDataObjects = projectDataObject.getClassDataObjects();
        for (ClassDataObject classDataObject : classDataObjects) {
            ClassComplexity complexity = classComplexityAnalyzer.analyze(classDataObjects, classDataObject);
            classDataObject.setClassComplexity(complexity);
            classDataObject.setComplexityScore(complexity.getComplexityScore());
        }
    }

    public void analyzeMethodComplexity(ProjectDataObject projectDataObject) {
        for (ClassDataObject classInfo : projectDataObject.getClassDataObjects()) {
            for (MethodDataObject methodInfo : classInfo.getMethods()) {
                MethodComplexity methodComplexity = methodComplexityAnalyzer.analyze(projectDataObject.getClassDataObjects(), methodInfo, classInfo);
                int score= methodComplexityAnalyzer.calculateComplexityScore(methodComplexity);
                methodInfo.setComplexityScore(score);
            }
        }
    }

    public void analyzeEntryPointComplexity(ProjectDataObject projectDataObject) {
        ClassComplexityAnalyzer classComplexityAnalyzer = new ClassComplexityAnalyzer();
    }

    public void saveClassInfo(ProjectDataObject projectDataObject) {
        List<JavaClassInfo> classInfoList = projectDataObject.toJavaClassInfo();
        for (JavaClassInfo classInfo : classInfoList) {
            classInfo.setProjectName(projectDataObject.getProjectName());
        }
        codeAnalysisDbService.saveClassInfo(classInfoList);
    }

    public void saveEntryPointInfo(ProjectDataObject projectDataObject) {
        List<EntryPointInfo> entryPointInfos = entryPointAnalyzer.analyze(projectDataObject);
        for (EntryPointInfo entryPointInfo : entryPointInfos) {
            entryPointInfo.setProjectName(projectDataObject.getProjectName());
        }
        codeAnalysisDbService.saveEntryPointData(entryPointInfos);
    }

    public void saveMethodInfo(ProjectDataObject projectDataObject) {
        List<JavaMethodInfo> methodInfos = projectDataObject.toJavaMethodInfo();
        for (JavaMethodInfo methodInfo : methodInfos) {
            methodInfo.setProjectName(projectDataObject.getProjectName());
            methodInfo.setComplexityScore(methodInfo.getCodeLines());
        }
        codeAnalysisDbService.saveMethodInfo(methodInfos);
    }

} 